#ifndef _I_API_PROGRAM_H_
#define _I_API_PROGRAM_H_

#include <stdlib.h>

#include "../interface/I_api_VertexShader.h"
#include "../interface/I_api_PixelShader.h"
#include "../interface/I_api_Blob.h"
#include "../interface/I_api_Buffer.h"
#include "../interface/I_api_SamplerState.h"

class I_api_ProgramMatrixVariable
{
public:
	I_api_ProgramMatrixVariable(){}
	~I_api_ProgramMatrixVariable(){}

	virtual	bool SetMatrix(float * pData)=0;
	virtual	bool SetMatrixArray(float * pData, int Offset, int Count)=0;
	virtual	bool SetMatrixTranspose(float * pData)=0;
	virtual	bool SetMatrixTransposeArray(float * pData, int Offset, int Count)=0;
};

class I_api_ProgramRenderTargetViewVariable
{
public:
	I_api_ProgramRenderTargetViewVariable(){}
	~I_api_ProgramRenderTargetViewVariable(){}

	virtual	bool SetRenderTarget(I_api_Buffer * pBuffer)=0;
	virtual	bool SetRenderTargetArray(I_api_Buffer ** ppBuffer, int Offset, int Count)=0;
};

class I_api_ProgramSamplerVariable
{
public:
	I_api_ProgramSamplerVariable(){}
	~I_api_ProgramSamplerVariable(){}

	virtual bool SetSampler(int index, I_api_SamplerState * pSampler)=0;
};

class I_api_ProgramScalarVariable
{
public:
	I_api_ProgramScalarVariable(){}
	~I_api_ProgramScalarVariable(){}

	virtual	bool	SetBool(bool Value)=0;
	virtual	bool	SetBoolArray(bool *pData, int Offset, int Count)=0;
	virtual	bool	SetFloat(float Value)=0;
	virtual	bool	SetFloatArray(float *pData, int Offset, int Count)=0;
	virtual	bool	SetInt(int Value)=0;
	virtual	bool	SetIntArray(int *pData, int Offset, int Count)=0;
};

class I_api_ProgramVectorVariable
{
public:
	I_api_ProgramVectorVariable(){}
	~I_api_ProgramVectorVariable(){}

	virtual	bool	SetBoolVector(bool *pData)=0;
	virtual	bool	SetBoolVectorArray(bool *pData, int Offset, int Count)=0;
	virtual	bool	SetFloatVector(float *pData)=0;
	virtual	bool	SetFloatVectorArray(float * pData, int Offset, int Count)=0;
	virtual	bool	SetIntVector(int * pData)=0;
	virtual	bool	SetIntVectorArray(int *pData, int Ofset, int Count)=0;
};

class I_api_ProgramVariable
{
protected:
	I_api_ProgramRenderTargetViewVariable	*	m_pRenderTargetView;
	I_api_ProgramMatrixVariable						*	m_pMatrix;
	I_api_ProgramSamplerVariable					*	m_pSampler;
	I_api_ProgramScalarVariable						*	m_pScalar;
	I_api_ProgramVectorVariable						*	m_pVector;

public:
	I_api_ProgramVariable()
	{
		m_pRenderTargetView = NULL;
		m_pMatrix = NULL;
		m_pSampler = NULL;
		m_pScalar = NULL;
		m_pVector = NULL;
	}
	~I_api_ProgramVariable(){}

	virtual	I_api_ProgramRenderTargetViewVariable	*	AsRenderTargetView() { return m_pRenderTargetView; }
	virtual	I_api_ProgramMatrixVariable						*	AsMatrix() { return m_pMatrix; }
	virtual	I_api_ProgramSamplerVariable					*	AsSampler() { return m_pSampler; }
	virtual	I_api_ProgramScalarVariable						*	AsScalar() { return m_pScalar; }
	virtual	I_api_ProgramVectorVariable						*	AsVector() { return m_pVector; }
};


class I_api_Program
{
	friend class I_api_Device;

protected:
	I_api_VertexShader *m_pVS;
	I_api_PixelShader *m_pPS;

	I_api_ProgramVariable	*	m_pProgramVariable;

	I_api_Program(I_api_VertexShader *pVS, I_api_PixelShader *pPS, I_api_Blob **ppErrorMsg)
	{
		m_pVS = pVS;
		m_pPS = pPS;
	}
public:
	I_api_Program()
	{
		m_pVS = NULL;
		m_pPS = NULL;
		m_pProgramVariable = NULL;
	}
	~I_api_Program()
	{
		m_pVS = NULL;
		m_pPS = NULL;
		delete m_pProgramVariable;
	}

	virtual	I_api_ProgramVariable	*	GetVariableByIndex(int index)=0;
	virtual	I_api_ProgramVariable	*	GetVariableByName(char * pName)=0;

	virtual	void	*	Get()=0;
};

#endif